package com.aspect;

import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.dto.RespBase;
import com.entity.User;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.service.UserService;

/**
 * 
 * @ClassName: LogAspect
 * @Description: 日志记录AOP实现
 * @author shaojian.yu
 * @date 2014年11月3日 下午1:51:59
 * 
 */
@Aspect
public class LogAspect {
	private final Logger logger = Logger.getLogger(this.getClass());
	@Resource
	private UserService userService;
	@Around("execution(* com.wn.controller.api4..*.*(..))")
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
		long uuid = System.currentTimeMillis()+(int)(Math.random()*1000);
		Gson gson = null;
		try {
			GsonBuilder gsonBuilder = new GsonBuilder();
		    gsonBuilder.serializeSpecialFloatingPointValues();
		    gson = gsonBuilder.create();

			long startTimeMillis = System.currentTimeMillis();
			RequestAttributes ra = RequestContextHolder.getRequestAttributes();
			ServletRequestAttributes sra = (ServletRequestAttributes) ra;
			HttpServletRequest request = sra.getRequest();
			Map<?, ?> inputParamMap = request.getParameterMap();
			// 获取请求地址
			String requestPath = request.getRequestURI();
//			logger.info("请求地址：" + requestPath);
			StringBuffer sb = new StringBuffer();
			Object[] args = pjp.getArgs();
			if (args != null) {
				for (Object obj : args) {
					if (obj instanceof HttpServletResponse)
						continue;
					if (obj instanceof HttpServletRequest) {
						continue;
					}
					sb.append(gson.toJson(obj));
				}
			}
			for (Enumeration<String> headerNames = request.getHeaderNames(); headerNames.hasMoreElements();) {
				String headerName = headerNames.nextElement();
				String value = request.getHeader(headerName);
				if (headerName.equalsIgnoreCase("Cookie"))
					sb.append(headerName).append(":").append(value).append(" ");
			}
			logger.info(uuid+"请求地址：" + requestPath + "  参数：" + gson.toJson(inputParamMap) + "  输入：" + sb.toString());

			ResponseFormat auth = getControllerMthodNeedLogin(pjp);
			if (auth == null || auth.needLogin()) {
				String json = null;
				Cookie uidcookie = getCookieByName(request, "uid");
				Cookie typecookie = getCookieByName(request, "lt");
				Cookie oauth = getCookieByName(request, "oauth");
				Cookie tokencookie = getCookieByName(request, "token");
				if (uidcookie == null || typecookie == null || tokencookie == null) {
					json = gson.toJson(new RespBase(RespBase.STATUS_ERR_COOKIE_EMPTY, "认证参数为空,请重新登录"));
					return json;
				}
				long uid = Long.parseLong(uidcookie.getValue());
				int type = Integer.valueOf(typecookie.getValue());
				String token = tokencookie.getValue().toString();
				String oauthvalue = oauth==null ? null:oauth.getValue().toString();
				User user = userService.getUserByCookie(uid, type,oauthvalue, token);
				if (user == null) {
					json = gson.toJson(new RespBase(RespBase.STATUS_ERR_TOKEN, "认证失败,请重新登录"));
				}
				if (json != null) {
					long endTimeMillis = System.currentTimeMillis();
					logger.info(uuid+
							"处理时间：" + (endTimeMillis - startTimeMillis) + "ms ;" + " " + requestPath + " 返回：" + json);
					return json;
				}
			}

			// 执行完方法的返回值：调用proceed()方法，就会触发切入点方法执行
			Object result = pjp.proceed();// result的值就是被拦截方法的返回值
			long endTimeMillis = System.currentTimeMillis();
			String json = gson.toJson(result);
			if(json.length()>300)
				json = json.substring(0,300)+"...";

			logger.info(uuid+"处理时间：" + (endTimeMillis - startTimeMillis) + "ms ;" + " " + requestPath + " 返回："+json);
			return result;
		} catch (Exception e) {
			logger.error(e);
			e.printStackTrace();
		} catch (Throwable e) {
			logger.error(e);
			e.printStackTrace();
		}
		return gson.toJson(new RespBase("系统异常"));
	}

	public static ResponseFormat getControllerMthodNeedLogin(JoinPoint joinPoint) throws Exception {
		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();
		Class targetClass = Class.forName(targetName);
		Method[] methods = targetClass.getMethods();
		ResponseFormat needLogin = null;
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				Class[] clazzs = method.getParameterTypes();
				if (clazzs.length == arguments.length) {
					needLogin = method.getAnnotation(ResponseFormat.class);
					break;
				}
			}
		}
		return needLogin;
	}


	/**
	 * 根据名字获取cookie
	 * 
	 * @param request
	 * @param name
	 *            cookie名字
	 * @return
	 */
	public static Cookie getCookieByName(HttpServletRequest request, String name) {
		Map<String, Cookie> cookieMap = ReadCookieMap(request);
		if (cookieMap.containsKey(name)) {
			Cookie cookie = (Cookie) cookieMap.get(name);
			return cookie;
		} else {
			return null;
		}
	}

	/**
	 * 将cookie封装到Map里面
	 * 
	 * @param request
	 * @return
	 */
	private static Map<String, Cookie> ReadCookieMap(HttpServletRequest request) {
		Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
		Cookie[] cookies = request.getCookies();
		if (null != cookies) {
			for (Cookie cookie : cookies) {
				cookieMap.put(cookie.getName(), cookie);
			}
		}
		return cookieMap;
	}
}